%% OFDMA主函数 - 正交频分多址仿真
% 本程序模拟了正交频分多址接入技术，这是第四代移动通信(4G)使用的多址接入技术
% 在OFDMA中，可用子载波在时间和频率域上被分配给不同用户

clear all;
close all;
clc;

%% 参数设置
num_users = 4;              % 用户数量
num_symbols = 10;           % OFDM符号数量
num_subcarriers = 256;      % 子载波数量
subcarriers_per_user = 64;  % 每个用户分配的子载波数量
cp_length = num_subcarriers/8; % 循环前缀长度（通常为1/4或1/8符号长度）
mod_type = 'QAM16';         % 调制类型: 'BPSK', 'QPSK', 'QAM16', 'QAM64'
snr_dB = 20;                % 信噪比(dB)

% 设置子载波分配策略
allocation_type = 'contiguous';  % 'contiguous'连续分配 或 'distributed'分布式分配

fprintf('OFDMA仿真开始，共%d个用户，%d个子载波，每用户%d个子载波\n', ...
    num_users, num_subcarriers, subcarriers_per_user);

%% 分配子载波给各用户
user_subcarriers = allocate_subcarriers(num_users, num_subcarriers, ...
    subcarriers_per_user, allocation_type);

fprintf('子载波分配完成\n');

%% 生成用户数据并调制
user_bits = cell(num_users, 1);
user_symbols = cell(num_users, 1);
user_mod_symbols = cell(num_users, 1);

fprintf('生成并调制用户数据...\n');
for user = 1:num_users
    % 计算用户比特数量，根据调制类型确定每符号比特数
    bits_per_symbol = get_bits_per_symbol(mod_type);
    num_bits = bits_per_symbol * subcarriers_per_user * num_symbols;
    
    % 生成随机比特
    user_bits{user} = randi([0 1], num_bits, 1);
    
    % 调制用户数据
    user_symbols{user} = modulate_qam(user_bits{user}, mod_type);
    
    % 重塑为每个OFDM符号对应的数据矩阵，每列是一个OFDM符号
    user_mod_symbols{user} = reshape(user_symbols{user}, subcarriers_per_user, num_symbols);
    
    fprintf('用户 %d 数据已生成和调制\n', user);
end

%% 生成OFDMA信号
% 初始化时频资源网格
resource_grid = zeros(num_subcarriers, num_symbols);

% 将每个用户的数据映射到其分配的子载波上
for user = 1:num_users
    subcarrier_indices = user_subcarriers{user};
    resource_grid(subcarrier_indices, :) = user_mod_symbols{user};
end

% 应用IFFT生成OFDM符号
time_domain_symbols = ifft(resource_grid, num_subcarriers);

% 添加循环前缀
ofdma_signal = add_cyclic_prefix(time_domain_symbols, cp_length);

% 串行化时域信号
ofdma_signal_serial = reshape(ofdma_signal, [], 1);

fprintf('OFDMA信号生成完成\n');

%% 通过信道传输
% 添加高斯白噪声
noisy_signal = add_awgn_to_ofdma(ofdma_signal_serial, snr_dB);

% 添加多径衰落（可选，默认启用）
fading_enable = true;
if fading_enable
    % 生成多径衰落信道
    channel_taps = [1.0 0.6*exp(1i*pi/3) 0.3*exp(1i*pi/6) 0.1*exp(1i*pi/4)];
    
    % 应用信道
    faded_signal = apply_multipath_channel(noisy_signal, channel_taps);
    
    % 信道估计和均衡（简化版本）
    received_signal = channel_equalization(faded_signal, channel_taps, noisy_signal);
else
    received_signal = noisy_signal;
end

fprintf('信号已通过信道传输\n');

%% 接收处理
% 重构为OFDM符号矩阵形式
received_signal_matrix = reshape(received_signal, num_subcarriers+cp_length, num_symbols);

% 去除循环前缀
received_symbols = remove_cyclic_prefix(received_signal_matrix, cp_length);

% 应用FFT恢复频域符号
received_freq_symbols = fft(received_symbols, num_subcarriers);

fprintf('接收信号FFT处理完成\n');

%% 解调和误码率计算
user_received_bits = cell(num_users, 1);
ber = zeros(num_users, 1);

fprintf('用户数据解调和误码率计算...\n');
for user = 1:num_users
    % 提取该用户的子载波数据
    subcarrier_indices = user_subcarriers{user};
    user_received_symbols = received_freq_symbols(subcarrier_indices, :);
    
    % 转换回串行格式
    user_received_symbols_serial = reshape(user_received_symbols, [], 1);
    
    % 解调接收符号
    user_received_bits{user} = demodulate_qam(user_received_symbols_serial, mod_type);
    
    % 计算误码率
    num_errors = sum(user_received_bits{user} ~= user_bits{user});
    ber(user) = num_errors / length(user_bits{user});
    
    fprintf('用户 %d 的误码率: %.6f\n', user, ber(user));
end

% 计算平均误码率
avg_ber = mean(ber);
fprintf('平均误码率: %.6f\n', avg_ber);

%% 可视化
fprintf('绘制OFDMA系统图形...\n');

% 绘制子载波分配
plot_subcarrier_allocation(user_subcarriers, num_subcarriers, num_users);

% 绘制资源网格
plot_resource_grid(resource_grid, num_users, user_subcarriers);

% 绘制时域信号和频谱
plot_ofdma_signals(time_domain_symbols, ofdma_signal, received_symbols);

fprintf('OFDMA仿真完成!\n'); 